/**
 * 
 */
package nl.boektrust.btsoep.shared.model;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;

import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.Id;

import com.google.gwt.user.client.rpc.IsSerializable;
import com.googlecode.objectify.annotation.Serialized;

/**
 * @author rao3
 *
 */
@Entity
public class Book implements Serializable,IsSerializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * 
	 */

	@Id Long id;

	private String title; // onix; ut
	private String subtitle; // onix; ut
	private LanguageCode languageCode; // onix; ut
	private LanguageCode originalLanguageCode; // onix ; ut
	private String originalTitle; // onix; ut
	@Serialized private ArrayList<URLReference> urlReferences;
	private ArrayList<Text> texts;
	@Embedded private ArrayList<ContentSpecifier> contentSpecifiers;
	@Serialized  private ArrayList<ISBNReference> isbnReferences;
	@Embedded private ArrayList<Contributor> contributors;  // onix; ut
	private Date modificationDate;
	private Date firstModificationDate;
	private ArrayList<String> titleWords;
	private ArrayList<String> contributorWords;
	

	/**
	 * @return the contributors
	 */
	public ArrayList<Contributor> getContributors() {
		return contributors;
	}
	
	/**
	 * @param title
	 */
	public Book(String title) {
		super();
		//System.err.println("Constructor title called");
		if (title.length() > 0) {
			this.title = title;
		} else {
			this.title = new String("");
		}
		this.subtitle = new String("");
		languageCode = LanguageCode.UNDEFINED;
		this.originalLanguageCode = LanguageCode.UNDEFINED;
		this.originalTitle = new String("");
		this.urlReferences = new ArrayList<URLReference>();
		texts = new ArrayList<Text>();
		contentSpecifiers = new ArrayList<ContentSpecifier>();
		this.isbnReferences = new ArrayList<ISBNReference>();
		contributors = new ArrayList<Contributor>();
	}
	
	public Book() {
		this("");
	}
	/**
	 * @return the title
	 */
	public String getTitle() {
		return title;
	}
	
	/**
	 * @param title the title to set
	 */
	public void setTitle(String title) {
		this.title = title;
	}
	/**
	 * @return the subtitle
	 */
	public String getSubtitle() {
		return subtitle;
	}
	/**
	 * @param subtitle the subtitle to set
	 */
	public void setSubtitle(String subtitle) {
		this.subtitle = subtitle;
	}
	/**
	 * @return the languageCode
	 */
	public LanguageCode getLanguageCode() {
		return languageCode;
	}
	/**
	 * @param languageCode the languageCode to set
	 */
	public void setLanguageCode(LanguageCode languageCode) {
		this.languageCode = languageCode;
	}
	/**
	 * @return the originalLanguageCode
	 */
	public LanguageCode getOriginalLanguageCode() {
		return originalLanguageCode;
	}
	/**
	 * @param originalLanguageCode the originalLanguageCode to set
	 */
	public void setOriginalLanguageCode(LanguageCode originalLanguageCode) {
		this.originalLanguageCode = originalLanguageCode;
	}
	/**
	 * @return the originalTitle
	 */
	public String getOriginalTitle() {
		return originalTitle;
	}
	/**
	 * @param originalTitle the originalTitle to set
	 */
	public void setOriginalTitle(String originalTitle) {
		this.originalTitle = originalTitle;
	}
	
	
	/**
	 * @return the urlReferences
	 */
	public ArrayList<URLReference> getUrlReferences() {
		return urlReferences;
	}
	/**
	 * @return the texts
	 */
	public ArrayList<Text> getTexts() {
		return texts;
	}
	
	/**
	 * @return the texts
	 */
	public ArrayList<String> getContributorWords() {
		return contributorWords;
	}
	/**
	 * @return the contentSpecifiers
	 */
	public ArrayList<ContentSpecifier> getContentSpecifiers() {
		return contentSpecifiers;
	}
	/**
	 * @return the isbnReferences
	 */
	public ArrayList<ISBNReference> getIsbnReferences() {
		return isbnReferences;
	}
	public void addText(Text t) {
		this.texts.add(t);
	}
	public void addURLReference(URLReference u) {
		this.urlReferences.add(u);
	}
	public void addISBNReference(ISBNReference i) {
		this.isbnReferences.add(i);
	}
	public void addContentSpecifier(ContentSpecifier c) {
		this.contentSpecifiers.add(c);
	}
	public void addContributor(Contributor c) {
		this.contributors.add(c);
	}
	/**
	 * @return the id
	 */
	public Long getId() {
		return id;
	}
	/**
	 * @param id the id to set
	 */
	public void setId(Long id) {
		this.id = id;
	}

	/**
	 * @return the modificationDate
	 */
	public Date getModificationDate() {
		return modificationDate;
	}

	/**
	 * @param modificationDate the modificationDate to set
	 */
	public void setModificationDate(Date modificationDate) {
		this.modificationDate = modificationDate;
	}

	/**
	 * @return the firstModificationDate
	 */
	public Date getFirstModificationDate() {
		return firstModificationDate;
	}

	/**
	 * @param firstModificationDate the firstModificationDate to set
	 */
	public void setFirstModificationDate(Date firstModificationDate) {
		this.firstModificationDate = firstModificationDate;
	}
	
	public String toPrintString() {
		String string = new String("");
		string = string +                       "id:                   " + id + "\n";
		if (title != null)    string = string + "title:                " + title + "\n";
		if (subtitle != null) string = string + "subtitle:             " + subtitle + "\n";
		string = string +                       "language code:        " + LanguageCode.stringValue(languageCode) + "\n";
		string = string +                        "original language code:" + LanguageCode.stringValue(originalLanguageCode) + "\n";
		if (originalTitle != null) string = string + "originalTitle:        " + originalTitle + "\n";
		if (modificationDate != null) {
			string = string + "modification date:              " + modificationDate.toString() + "\n";
		} else {
			string = string + "modification date: NULL " + "\n";
		}
		if (firstModificationDate != null) {
			string = string + "first modification date:        " + firstModificationDate.toString()+"\n";
		} else {
			string = string + "first modification date: NULL\n";

		}
		for (URLReference u : urlReferences) {
			string = string + "URL Reference:\n";
			string = string + "url reference type:" + URLReferenceType.stringValue(u.getUrlReferenceType()) + "\n";
			string = string + "url:" + u.getUrl() + "\n";
		}
		for (ISBNReference i : isbnReferences) {
			string = string + "ISBN Reference:\n";
			try {
				string = string + "isbn reference type:" + ISBNReferenceType.stringValue(i.getIsbnReferenceType()) + "\n";
				if (i.getIsbn() != null && i.getIsbn().getIsbn13() != null) string = string + "isbn:" + i.getIsbn().getIsbn13() + "\n";
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (contributors.size() == 0) {
			string = string + "No contributors\n";
		} else {
			for (Contributor c : contributors) {
				string = string + "Contributor: \n";
				string = string + c.toPrintString();
			}
		}
		if (contentSpecifiers.size() == 0) {
			string = string + "No contentSpecifiers\n";
		} else {
			for (ContentSpecifier c : contentSpecifiers) {
				string = string + "contentSpecifier: \n";
				string = string + c.toPrintString();
			}
		}
		return string;
		
	}
	
	@javax.persistence.PrePersist
	@javax.persistence.PreUpdate
	public void populateParsedTitleArray() {
		String str = this.getTitle();
		//System.err.println("prepersist title: "+str);
		 this.titleWords = new ArrayList<String>();
         int pos = 0, end;
         while ((end = str.indexOf(' ', pos)) >= 0) {
        	 String word = str.substring(pos, end).toLowerCase();
        	 if (StopWords.isAStopWord(word) == false && word.length()>1) this.titleWords.add(word);
             pos = end + 1;
         }
         String word = str.substring(pos, str.length()).toLowerCase();
    	 if (StopWords.isAStopWord(word) == false && word.length()>1) this.titleWords.add(word);
    	 /*
         System.err.print("Parsed as: ");
         for (String s : this.titleWords) {
        	 System.err.print(s);
        	 System.err.print(", ");
         }
         System.err.println("");
         */
	}
	
	@javax.persistence.PrePersist
	@javax.persistence.PreUpdate
	public void populateContributorNamesOnBook() {
		//System.err.println("prepersist populateContributorNamesOnBook: ");
		this.contributorWords = new ArrayList<String>();
		for (Contributor c : this.getContributors()) {
			ArrayList<String> strings = c.populateParsedNameOnBook();
			for (String s : strings) {
				/*
				 * test to make sure that no word that already exists in contributorWords is added.
				 */
				boolean exists = false;
				for (String existing_s : this.contributorWords) {
					if (existing_s.equals(s)) exists = true;
					break;
				}
				if (exists == false) this.contributorWords.add(s); 
			}
		}
		/*
		System.err.println("Populating contributorWords: ");
		for (String w : this.contributorWords) {
			System.err.println("contributor word: "+w);
		}
		*/
	}

}
